package buyChance

import (
	//	"fmt"
	"net"
	"strconv"
	"strings"
	"sync"
)
import (
	"github.com/Damnever/goqueue"
)
import (
	"r_log"
	"resource"
	"util"
)

type PacketReceived struct {
	head SDds_C2P_PHead
	b1   []byte
}

/*************************************************************
本包是一个和dds服务器交互的长连接，因此有一个常驻发送线程和一个常驻接收线程。
常驻接收线程接到的包会放到接收队列里，需要发送的包放到发送队列里，常驻发送线程会取出并发送
/*********************************************************************/
type DataSocket struct {
	Port         int               //监听端口
	ReceiveQueue *goqueue.Queue    //接收队列
	ThreadChan   chan int          //处理接收包的线程数
	StkMapSH     map[uint32]string //上证代码表
	StkMapSZ     map[uint32]string //深证代码表
	MktMapSH     map[string]uint32
	MktMapSZ     map[string]uint32
	StkMapLock   sync.RWMutex //代码表操作锁
	InitFlagSH   bool         //上证代码表初始化标记
	InitFlagSZ   bool         //深证代码表初始化标记
	InitFlag     bool         //是否初始化过
	Conn         net.Conn
	ConnectCount int
}

func (s *DataSocket) InitData(port int, threadnum int) {
	s.Port = port
	//	s.ToSendQueue = goqueue.New(0)
	s.ReceiveQueue = goqueue.New(0)
	s.ThreadChan = make(chan int, threadnum)
	s.StkMapSH = make(map[uint32]string)
	s.StkMapSZ = make(map[uint32]string)
	s.MktMapSH = make(map[string]uint32)
	s.MktMapSZ = make(map[string]uint32)
	s.InitFlagSH = false
	s.InitFlagSZ = false
	s.InitFlag = false
}

func (s *DataSocket) StartService(port int, threadnum int) {

	s.InitData(port, threadnum)

	s.StartListener()
}

func (s *DataSocket) StartListener() {
	l, err := net.Listen("tcp", ":"+strconv.Itoa(s.Port))
	if err != nil {
		r_log.Logger.Error("StartListener():Listen():%v", err)
		return
	}
	go s.DealPacket()
	for {
		c, err := l.Accept()
		if err != nil {
			r_log.Logger.Error("StartListener():Accept():%v", err)
			return
		}
		exitchan := make(chan int, 1)
		//处理
		s.Conn = c
		s.ConnectCount++
		go s.ReceiveMessage(c, &exitchan)
		//go s.SendMessage(c, &exitchan)
	}
}

func (s *DataSocket) ReceiveMessage(c net.Conn, exitchan *chan int) { //常驻接收线程
	defer c.Close()
	defer func() {
		s.InitFlagSZ = false
		s.InitFlagSH = false
		s.InitFlag = false
		s.ConnectCount--
	}()
	for {
		b := make([]byte, 6)
		n, err := c.Read(b)
		if err != nil {
			r_log.Logger.Error("ReceiveMessage():%v", err)
			(*exitchan) <- 1
			return
		}
		if n < 6 {
			_, err = c.Read(b[n:])
			if err != nil {
				r_log.Logger.Error("ReceiveMessage():%v", err)
				(*exitchan) <- 1
				return
			}
		}
		var head SDds_C2P_PHead
		head.WPid = util.Byte2Uint16(b[:2])
		head.DwLen = util.Byte2Uint32(b[2:6])

		length := head.DwLen - 6
		var b1 []byte
		if length > 0 {
			b1 = make([]byte, length)
			b2 := b1
			n = 0
			for n < int(length) {
				m, err1 := c.Read(b2)
				b2 = b2[m:]
				n += m
				if err1 != nil {
					r_log.Logger.Error("ReceiveMessage():%v", err)
					(*exitchan) <- 1
					return
				}
			}
		}
		var pak PacketReceived
		pak.head = head
		pak.b1 = b1
		s.ReceiveQueue.Put(pak, 0)

	}
}

func (s *DataSocket) DealPacket() { //接收包处理线程
	for {
		i, _ := s.ReceiveQueue.Get(0)
		pak := i.(PacketReceived)
		head := pak.head
		b1 := pak.b1
		switch head.WPid {
		case PID_DDS_PY_MARKET_DATE_LIST: //日期更新
			var data SDdsPYMarketDateListA
			data.Head = head
			data.DwCount = util.Byte2Uint32(b1[:4])
			data.DwReserved[0] = util.Byte2Uint32(b1[4:8])
			data.DwReserved[1] = util.Byte2Uint32(b1[8:12])
			data.PItem = make([]SDdsPYMarketDateListAItem, data.DwCount)
			bt := b1[12:]
			for i := 0; i < int(data.DwCount); i++ {
				data.PItem[i].IdMarket = string(bt[:4])
				data.PItem[i].DwHQDate = util.Byte2Uint32(bt[4:8])
				data.PItem[i].DwReserved = util.Byte2Uint32(bt[8:12])
				bt = bt[12:]
			}
			//			s.DealMARKET_DATE_LIST(data)
		case PID_DDS_PY_CN_LIST: //代码表
			var data SDdsPYCNListA
			data.Head = head
			data.IdMarket = string(b1[:4])
			data.DwCount = util.Byte2Uint32(b1[4:8])
			data.DwReserved[0] = util.Byte2Uint32(b1[8:12])
			data.DwReserved[1] = util.Byte2Uint32(b1[12:16])
			data.PItem = make([]SDdsPYCNListAItem, data.DwCount)
			bt := b1[16:]
			for i := 0; i < int(data.DwCount); i++ {
				data.PItem[i].IdStk = util.Byte2Uint32(bt[:4])
				data.PItem[i].SzMarketCode = string(bt[4:17])
				bt = bt[38:]
			}
			s.DealPY_CN_LIST(data)
		case PID_DDS_PY_OPEN_INFO: //开盘信息
			//			var data SDdsPYOpenInfoA
			//			data.Head = head
			//			data.DwDate = util.Byte2Uint32(b1[:4])
			//			data.IdMarket = string(b1[4:8])
			//			data.DwCount = util.Byte2Uint32(b1[8:12])
			//			data.DwReserved[0] = util.Byte2Uint32(b1[12:16])
			//			data.DwReserved[1] = util.Byte2Uint32(b1[16:20])
			//			data.PItem = make([]SDdsPYOpenInfoAItem, data.DwCount)
			//			bt := b1[20:]
			//			for i := 0; i < int(data.DwCount); i++ {
			//				data.PItem[i].IdStk = util.Byte2Uint32(bt[:4])
			//				data.PItem[i].FLastClose = util.Byte2Float32(bt[4:8])
			//				data.PItem[i].FAve5Vol = util.Byte2Float32(bt[8:12])
			//				data.PItem[i].FTq = util.Byte2Float32(bt[12:16])
			//				data.PItem[i].FDr = util.Byte2Float32(bt[16:20])
			//				bt = bt[20:]
			//			}
		case PID_DDS_PY_SNAP:
			//			var data SDdsPYSnanpA
			//			data.Head = head
			//			data.IdMarket = string(b1[:4])
			//			data.IdDyn = util.Byte2Uint16(b1[4:6])
			//			data.IdStk = util.Byte2Uint32(b1[6:10])
			//			data.WItemSize = util.Byte2Uint16(b1[10:12])
			//			data.DwCount = util.Byte2Uint32(b1[12:16])
			//			data.DwReserved[0] = util.Byte2Uint32(b1[16:20])
			//			data.DwReserved[1] = util.Byte2Uint32(b1[20:24])
			//			data.Data = b1[24:]

		case PID_DDS_PY_PUSH: //推送包
			var data SDdsPYPushA
			data.Head = head
			data.IdMarket = string(b1[:4])
			data.IdDyn = util.Byte2Uint16(b1[4:6])
			data.IdStk = util.Byte2Uint32(b1[6:10])
			data.WItemSize = util.Byte2Uint16(b1[10:12])
			data.DwCount = util.Byte2Uint32(b1[12:16])
			data.DwReserved[0] = util.Byte2Uint32(b1[16:20])
			data.DwReserved[1] = util.Byte2Uint32(b1[20:24])
			data.Data = b1[24:]

			switch data.IdDyn {
			case 83:
				var ret SDds_I_Dyn_Stk_L1
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal83(ret)
			//444-447:日线，二小时线，一小时线，半小时线的预警信号
			/*
				case 444:
					var ret SDds_Quantitative_Model_RawFlag
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal444(ret)
				case 445:
					var ret SDds_Quantitative_Model_RawFlag
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal445(ret)
				case 446:
					var ret SDds_Quantitative_Model_RawFlag
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal446(ret)
				case 447:
					var ret SDds_Quantitative_Model_RawFlag
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal447(ret)*/
			//				456-459:日线，二小时线，一小时线，半小时线的滤网信息
			case 523:
				var ret SDds_Quantitative_ModelFilter
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal523(ret)
			case 524:
				var ret SDds_Quantitative_ModelFilter
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal524(ret)
			case 525:
				var ret SDds_Quantitative_ModelFilter
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal525(ret)
			case 526:
				var ret SDds_Quantitative_ModelFilter
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal526(ret)

				//502-505:日线，二小时线，一小时线，半小时线的预警信号
			case 502:

				var ret SDds_I_Quantitative_RawFlag_V2
				ret.Decode(data.Data)
				//fmt.Println(502, ret)
				s.ThreadChan <- 1
				go s.Deal502(ret)
			case 503:
				var ret SDds_I_Quantitative_RawFlag_V2
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal503(ret)
			case 504:
				var ret SDds_I_Quantitative_RawFlag_V2
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal504(ret)
			case 505:
				var ret SDds_I_Quantitative_RawFlag_V2
				ret.Decode(data.Data)
				s.ThreadChan <- 1
				go s.Deal505(ret)

			default:

				//				fmt.Println(data.IdDyn)
			}
		case PID_DDS_PY_PATCH: //patch包的应答包
			var data SDdsPYPatchA
			data.Head = head
			data.IdMarket = string(b1[:4])
			data.IdDyn = util.Byte2Uint16(b1[4:6])
			data.IdStk = util.Byte2Uint32(b1[6:10])
			data.WItemSize = util.Byte2Uint16(b1[10:12])
			data.DwCount = util.Byte2Uint32(b1[12:16])
			data.DwReserved[0] = util.Byte2Uint32(b1[16:20])
			data.DwReserved[1] = util.Byte2Uint32(b1[20:24])
			data.Data = b1[24:]
			if data.DwCount > 0 {
				switch data.IdDyn {
				case 83:
					var ret SDds_I_Dyn_Stk_L1
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal83Patch(ret)
				/*
					//444-447:日线，二小时线，一小时线，半小时线的预警信号
					case 444:
						var ret SDds_Quantitative_Model_RawFlag
						ret.Decode(data.Data)
						s.ThreadChan <- 1
						go s.Deal444Patch(ret)
					case 445:
						var ret SDds_Quantitative_Model_RawFlag
						ret.Decode(data.Data)
						s.ThreadChan <- 1
						go s.Deal445Patch(ret)
					case 446:
						var ret SDds_Quantitative_Model_RawFlag
						ret.Decode(data.Data)
						s.ThreadChan <- 1
						go s.Deal446Patch(ret)
					case 447:
						var ret SDds_Quantitative_Model_RawFlag
						ret.Decode(data.Data)
						s.ThreadChan <- 1
						go s.Deal447Patch(ret)*/
				//456-459:日线，二小时线，一小时线，半小时线的滤网信息
				case 523:
					var ret SDds_Quantitative_ModelFilter
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal523Patch(ret)
				case 524:
					var ret SDds_Quantitative_ModelFilter
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal524Patch(ret)
				case 525:
					var ret SDds_Quantitative_ModelFilter
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal525Patch(ret)
				case 526:
					var ret SDds_Quantitative_ModelFilter
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal526Patch(ret)

					//502-505:日线，二小时线，一小时线，半小时线的预警信号
				case 502:
					var ret SDds_I_Quantitative_RawFlag_V2
					ret.Decode(data.Data)
					//fmt.Println("502Patch", ret)
					s.ThreadChan <- 1
					go s.Deal502Patch(ret)
				case 503:
					var ret SDds_I_Quantitative_RawFlag_V2
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal503Patch(ret)
				case 504:
					var ret SDds_I_Quantitative_RawFlag_V2
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal504Patch(ret)
				case 505:
					var ret SDds_I_Quantitative_RawFlag_V2
					ret.Decode(data.Data)
					s.ThreadChan <- 1
					go s.Deal505Patch(ret)
				}
			} else {

			}
		case PID_DDS_PY_PRICE_LIST: //分价表应答包
			//			var data SDdsPYPriceListA
			//			data.Head = head
			//			data.IdMarket = string(b1[:4])
			//			data.IdStk = util.Byte2Uint32(b1[4:8])
			//			data.DwLastHqTime = util.Byte2Uint32(b1[8:12])
			//			data.N64LastVolume = util.Byte2Int64(b1[12:20])
			//			data.N64LastAmount = util.Byte2Int64(b1[20:28])
			//			data.WDecm = util.Byte2Uint16(b1[28:30])
			//			data.DwCount = util.Byte2Uint32(b1[30:34])
			//			data.DwReserved[0] = util.Byte2Uint32(b1[34:38])
			//			data.DwReserved[1] = util.Byte2Uint32(b1[38:42])
			//			data.DwReserved[2] = util.Byte2Uint32(b1[42:46])
			//			data.PItem = make([]SDdsPYPriceListAItem, data.DwCount)
			//			bt := b1[46:]
			//			for i := 0; i < int(data.DwCount); i++ {
			//				data.PItem[i].NPrice = util.Byte2Uint32(bt[:4])
			//				data.PItem[i].FBugVolume = util.Byte2Float32(bt[4:8])
			//				data.PItem[i].FSellVolume = util.Byte2Float32(bt[8:12])
			//				bt = bt[12:]
			//			}
		}
	}
}

func (s *DataSocket) SendMessage(b []byte) { //常驻发送线程
	if s.Conn == nil {
		r_log.Logger.Error("SendMessage(): 连接出错")
		return
	}
	l := len(b)
	n := 0
	for n < l {
		m, err := s.Conn.Write(b[n:])
		n += m
		if err != nil {
			r_log.Logger.Error("SendMessage(): %v", err)
			return
		}
	}
}

/*
func (s *DataSocket) SendPYPatch(pak SDdsPYPatch) { //patch包发送
	b := pak.Encode()
	s.ToSendQueue.Put(b, 0)
}
func (s *DataSocket) SendPYPriceList(pak SDdsPYPriceList) { //分价表查询包发送
	b := pak.Encode()
	s.ToSendQueue.Put(b, 0)
}*/

//BuyChance
func (s *DataSocket) Deal444(data SDds_Quantitative_Model_RawFlag) { //日线
	buyChanceUpdate(data, util.PERIOD_DAY, false)
	<-s.ThreadChan
}
func (s *DataSocket) Deal445(data SDds_Quantitative_Model_RawFlag) { //两小时线
	buyChanceUpdate(data, util.PERIOD_2HOUR, false)
	<-s.ThreadChan
}
func (s *DataSocket) Deal446(data SDds_Quantitative_Model_RawFlag) {
	buyChanceUpdate(data, util.PERIOD_HOUR, false)
	<-s.ThreadChan
}
func (s *DataSocket) Deal447(data SDds_Quantitative_Model_RawFlag) {
	buyChanceUpdate(data, util.PERIOD_HHOUR, false)
	<-s.ThreadChan
}

func (s *DataSocket) Deal502(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_DAY, false)
	<-s.ThreadChan
}
func (s *DataSocket) Deal503(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_2HOUR, false)
	<-s.ThreadChan
}
func (s *DataSocket) Deal504(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_HOUR, false)
	<-s.ThreadChan
}
func (s *DataSocket) Deal505(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_HHOUR, false)
	<-s.ThreadChan
}

//BuyChance Update
func buyChanceUpdate(data SDds_Quantitative_Model_RawFlag, p util.Period, isPatch bool) {
	bc := convertBC(data, p, false)
	if bc != nil {
		BCBase.BcLock[p].Lock()
		bcs := BCBase.BuyChances[p]
		if bcs.Date < bc.Date || (bcs.Date == bc.Date && bcs.Time < bc.Time) {
			if !isPatch {
				r_log.BCLogger.Info("BC(period = %v, isPatch = %v): update timestamp(bcs date = %v, time = %v): %v", p, isPatch, bcs.Date, bcs.Time, *bc)
			}
			bcs.BcMap = make(map[util.StkID]*BuyChance)
			bcs.BcSlice = make([]*BuyChance, 0)
			bcs.Date = bc.Date
			bcs.Time = bc.Time
		}
		if util.GeneratorTimestamp(bc.Date, bc.Time) == util.GeneratorTimestamp(bcs.Date, bcs.Time) {
			r_log.BCLogger.Info("BC(period = %v, isPatch = %v): record bc: %v", p, isPatch, *bc)
			if _, ok := bcs.BcMap[bc.Stkid]; ok {
				r_log.Logger.Warn("buyChanceUpdate(): receive duplicate pack, stk= %v, date=%v, time=%v", bc.Stkid, bcs.Date, bcs.Time)
			}
			bcs.BcMap[bc.Stkid] = bc
			bcs.BcSlice = append(bcs.BcSlice, bc)
		} else {
			r_log.BCLogger.Info("BC(period = %v, isPatch = %v): unrecord bc: %v", p, isPatch, *bc)
		}
		BCBase.BcLock[p].Unlock()
	}
}

//BuyChance Update V2
func (s *DataSocket) buyChanceUpdateV2(data SDds_I_Quantitative_RawFlag_V2, p util.Period, isPatch bool) {
	//fmt.Println("u1111")
	if !s.IsStockOK(data.Info.IdStk) {
		return
	}
	//fmt.Println("u2222")
	bc := s.convertBCV2(data, p, false)
	bc.IsInChooseMap = s.IsStockInChooseMap(data.Info.IdStk)
	//fmt.Println("u3333")
	if bc != nil {
		//fmt.Println("u3000")
		BCBase.BcLock[p].Lock()
		bcs := BCBase.BuyChances[p]
		//fmt.Println("u3001")
		if bcs.Date < bc.Date || (bcs.Date == bc.Date && bcs.Time < bc.Time) {
			//fmt.Println("u3111")
			if !isPatch {
				r_log.BCLogger.Info("BC(period = %v, isPatch = %v): update timestamp(bcs date = %v, time = %v): %v", p, isPatch, bcs.Date, bcs.Time, *bc)
			}
			bcs.BcMap = make(map[util.StkID]*BuyChance)
			bcs.BcSlice = make([]*BuyChance, 0)
			bcs.Date = bc.Date
			bcs.Time = bc.Time
		}
		if util.GeneratorTimestamp(bc.Date, bc.Time) == util.GeneratorTimestamp(bcs.Date, bcs.Time) {
			//fmt.Println("u3222")
			r_log.BCLogger.Info("BC(period = %v, isPatch = %v): record bc: %v", p, isPatch, *bc)
			if _, ok := bcs.BcMap[bc.Stkid]; ok {
				r_log.Logger.Warn("buyChanceUpdate(): receive duplicate pack, stk= %v, date=%v, time=%v", bc.Stkid, bcs.Date, bcs.Time)
			}
			bcs.BcMap[bc.Stkid] = bc
			idx := 0
			for ; idx < len(bcs.BcSlice); idx++ {
				if bc.NProfitRate > bcs.BcSlice[idx].NProfitRate {
					break
				}
			}
			bcstemp := append(bcs.BcSlice[:idx], bc)
			bcs.BcSlice = append(bcstemp, bcs.BcSlice[idx:]...)
		} else {
			//fmt.Println("u3333")
			r_log.BCLogger.Info("BC(period = %v, isPatch = %v): unrecord bc: %v", p, isPatch, *bc)
		}
		BCBase.BcLock[p].Unlock()
	}
	//fmt.Println("u4444")
}

func (s *DataSocket) IsStockOK(stkid uint32) bool {
	if stkid == 154052 {
		return false
	}
	if marketcode, ok := s.StkMapSH[stkid]; ok {
		resource.ExitLock.Lock()
		if _, eok := resource.ExitStockList[marketcode]; eok {
			resource.ExitLock.Unlock()
			return false
		}
		resource.ExitLock.Unlock()
	}
	if marketcode, ok := s.StkMapSZ[stkid]; ok {
		resource.ExitLock.Lock()
		if _, eok := resource.ExitStockList[marketcode]; eok {
			resource.ExitLock.Unlock()
			return false
		}
		resource.ExitLock.Unlock()
	}
	return true
}

func (s *DataSocket) IsStockInChooseMap(stkid uint32) bool {
	if marketcode, ok := s.StkMapSH[stkid]; ok {
		resource.ChooseLock.Lock()
		if _, cok := resource.ChooseStockList[marketcode]; cok {
			resource.ChooseLock.Unlock()
			return true
		}
		resource.ChooseLock.Unlock()
	}
	if marketcode, ok := s.StkMapSZ[stkid]; ok {
		resource.ChooseLock.Lock()
		if _, cok := resource.ChooseStockList[marketcode]; cok {
			resource.ChooseLock.Unlock()
			return true
		}
		resource.ChooseLock.Unlock()
	}
	return false
}

//BuyChance patch
func (s *DataSocket) Deal444Patch(data SDds_Quantitative_Model_RawFlag) {
	buyChanceUpdate(data, util.PERIOD_DAY, true)
	<-s.ThreadChan
}
func (s *DataSocket) Deal445Patch(data SDds_Quantitative_Model_RawFlag) {
	buyChanceUpdate(data, util.PERIOD_2HOUR, true)
	<-s.ThreadChan
}
func (s *DataSocket) Deal446Patch(data SDds_Quantitative_Model_RawFlag) {
	buyChanceUpdate(data, util.PERIOD_HOUR, true)
	<-s.ThreadChan
}
func (s *DataSocket) Deal447Patch(data SDds_Quantitative_Model_RawFlag) {
	buyChanceUpdate(data, util.PERIOD_HHOUR, true)
	<-s.ThreadChan
}

//BuyChance patch
func (s *DataSocket) Deal502Patch(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_DAY, true)
	<-s.ThreadChan
}
func (s *DataSocket) Deal503Patch(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_2HOUR, true)
	<-s.ThreadChan
}
func (s *DataSocket) Deal504Patch(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_HOUR, true)
	<-s.ThreadChan
}
func (s *DataSocket) Deal505Patch(data SDds_I_Quantitative_RawFlag_V2) {
	s.buyChanceUpdateV2(data, util.PERIOD_HHOUR, true)
	<-s.ThreadChan
}

//ModelFilter
func (s *DataSocket) Deal523(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_DAY)
	<-s.ThreadChan
}
func (s *DataSocket) Deal524(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_2HOUR)
	<-s.ThreadChan
}
func (s *DataSocket) Deal525(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_HOUR)
	<-s.ThreadChan
}
func (s *DataSocket) Deal526(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_HHOUR)
	<-s.ThreadChan
}

//ModelFilter Update
func mfUpdate(data SDds_Quantitative_ModelFilter, p util.Period) { //注意比较和已有数据的时间
	mf := convertMF(data)
	BCBase.MfLocks[p].Lock()
	older, ok := BCBase.ModeFilters[p][mf.Stkid]
	if !ok || util.GeneratorTimestamp(older.Date, older.Time) < util.GeneratorTimestamp(mf.Date, mf.Time) {
		r_log.BCLogger.Info("MF(period = %v, isPatch = %v): update mf: %v", p, false, mf)
		BCBase.ModeFilters[p][mf.Stkid] = &mf
	} else {
		r_log.BCLogger.Info("MF(period = %v, isPatch = %v): filter mf: %v", p, false, mf)
	}
	BCBase.MfLocks[p].Unlock()
}

//ModelFilter Patch
func (s *DataSocket) Deal523Patch(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_DAY)
	<-s.ThreadChan
}
func (s *DataSocket) Deal524Patch(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_2HOUR)
	<-s.ThreadChan
}
func (s *DataSocket) Deal525Patch(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_HOUR)
	<-s.ThreadChan
}
func (s *DataSocket) Deal526Patch(data SDds_Quantitative_ModelFilter) {
	mfUpdate(data, util.PERIOD_HHOUR)
	<-s.ThreadChan
}

//代码表处理函数
func (s *DataSocket) DealPY_CN_LIST(data SDdsPYCNListA) {
	if data.IdMarket == "SHHQ" {
		s.StkMapLock.Lock()
		for i := 0; i < int(data.DwCount); i++ {
			if strings.HasPrefix(data.PItem[i].SzMarketCode, "SHHQ6") {
				s.StkMapSH[data.PItem[i].IdStk] = data.PItem[i].SzMarketCode[:10]
				//mc:=strings.TrimSpace(data.PItem[i].SzMarketCode)
				s.MktMapSH[data.PItem[i].SzMarketCode[:10]] = data.PItem[i].IdStk
			}
		}
		s.StkMapLock.Unlock()
		s.InitFlagSH = true
	}
	if data.IdMarket == "SZHQ" {
		s.StkMapLock.Lock()
		for i := 0; i < int(data.DwCount); i++ {
			if strings.HasPrefix(data.PItem[i].SzMarketCode, "SZHQ30") || strings.HasPrefix(data.PItem[i].SzMarketCode, "SZHQ00") {
				s.StkMapSZ[data.PItem[i].IdStk] = data.PItem[i].SzMarketCode[:10]
				s.MktMapSZ[data.PItem[i].SzMarketCode[:10]] = data.PItem[i].IdStk
			}
		}
		s.StkMapLock.Unlock()
		s.InitFlagSZ = true
	}
	if !s.InitFlag {
		if s.InitFlagSH && s.InitFlagSZ {
			s.InitAll()
			s.InitFlag = true
		}
	}
}

func (s *DataSocket) PatchStrainerPackage(Market string, Stkid uint32, DynId uint16, MinDate uint32, MinTime uint32) {
	var strainerPatch SDdsPYPatch
	strainerPatch.DwMaxTime = 99999999
	strainerPatch.DwMinTime = MinTime
	strainerPatch.DwMaxDate = 99999999
	strainerPatch.DwMinDate = MinDate
	strainerPatch.Head.WPid = PID_DDS_PY_PATCH
	strainerPatch.Head.DwLen = 48
	strainerPatch.IdMarket = Market
	strainerPatch.IdStk = Stkid
	strainerPatch.IdDyn = DynId
	strainerPatch.NNeedCount = -1
	b := strainerPatch.Encode()
	s.SendMessage(b)
}

//
func (s *DataSocket) InitStrainer(date uint32, time uint32) {
	s.StkMapLock.RLock()
	for k, _ := range s.StkMapSH {
		for i := uint16(523); i < 527; i++ {
			s.PatchStrainerPackage("SHHQ", k, i, date, time)
		}
	}
	for k, _ := range s.StkMapSZ {
		for i := uint16(523); i < 527; i++ {
			s.PatchStrainerPackage("SZHQ", k, i, date, time)
		}
	}
	s.StkMapLock.RUnlock()
}

func (s *DataSocket) PatchBcPackage(Market string, Stkid uint32, DynId uint16, MaxDate uint32, MaxTime uint32) {
	var bcPatch SDdsPYPatch
	bcPatch.DwMaxTime = MaxTime
	bcPatch.DwMinTime = 0
	bcPatch.DwMaxDate = MaxDate
	bcPatch.DwMinDate = 0
	bcPatch.Head.WPid = PID_DDS_PY_PATCH
	bcPatch.Head.DwLen = 48
	bcPatch.IdMarket = Market
	bcPatch.IdStk = Stkid
	bcPatch.IdDyn = DynId
	bcPatch.NNeedCount = -1
	b := bcPatch.Encode()
	s.SendMessage(b)
}
func (s *DataSocket) InitBc(date uint32, time uint32) {
	for k, _ := range s.StkMapSH {
		for i := uint16(444); i < 448; i++ {
			s.PatchBcPackage("SHHQ", k, i, date, time)
		}
	}
	for k, _ := range s.StkMapSZ {
		for i := uint16(444); i < 448; i++ {
			s.PatchBcPackage("SZHQ", k, i, date, time)
		}
	}
	//return true
}

func (s *DataSocket) InitBcV2(date uint32, time uint32) {
	for k, _ := range s.StkMapSH {
		for i := uint16(502); i < 506; i++ {
			s.PatchBcPackage("SHHQ", k, i, date, time)
		}
	}
	for k, _ := range s.StkMapSZ {
		for i := uint16(502); i < 506; i++ {
			s.PatchBcPackage("SZHQ", k, i, date, time)
		}
	}
	//return true
}

func (s *DataSocket) InitAll() {
	var strainerdate, strainertime, bcdate, bctime uint32
	//Todo获取补数时间
	bcdate = uint32(util.Today())
	bctime = 999999
	s.InitStrainer(strainerdate, strainertime)
	//s.InitBc(bcdate, bctime)
	s.InitBcV2(bcdate, bctime)
}

//buychance预警包结构转换
func convertBC(data SDds_Quantitative_Model_RawFlag, p util.Period, isPatch bool) (bc *BuyChance) {
	bc = new(BuyChance)
	bc.Type = util.ModeType(data.DwModel) | util.MODE_SUIJI_202 | util.MODE_SUIJI_201
	bc.Type = bc.Type - util.MODE_SUIJI_202 - util.MODE_SUIJI_201
	if bc.Type == 0 {
		r_log.BCLogger.Info("BC(period = %v, isPatch = %v): filter suiji: stkid=%v", p, isPatch, data.Info.IdStk)
		return nil
	}
	if util.ModeType(data.DwModel)&MODE_ZHENDANG2 > 0 {
		bc.Type -= MODE_ZHENDANG2
		bc.Type = bc.Type | MODE_ZHENDANG
	}
	if util.ModeType(data.DwModel)&MODE_BOTHCHAODIE > 0 {
		bc.Type -= MODE_BOTHCHAODIE
		bc.Type = bc.Type | MODE_CHAODIE
	}
	bc.Stkid = util.StkID(data.Info.IdStk)
	bc.Price[0] = data.NClose / 10
	bc.Price[1] = data.NPrice50 / 10
	bc.Price[2] = data.NPrice70 / 10
	bc.Price[3] = data.NPrice80 / 10
	bc.Price[4] = data.NPrice85 / 10
	bc.Price[5] = data.NPrice95 / 10
	bc.AvgTransaction = data.NAvgAmount5 * 100
	bc.Date = util.DateAndTime(data.Info.DwDate)
	bc.Level = util.LEVEL_UNKNOWN
	bc.CountinueLose = data.NCountinueLose > 0
	bc.Time = util.DateAndTime(data.Info.DwUion)
	if bc.Time > 150000 || p == util.PERIOD_DAY {
		bc.Time = 150000 //data.Info.DwUion
	}

	return
}

//buychance预警包结构转换
func (s *DataSocket) convertBCV2(data SDds_I_Quantitative_RawFlag_V2, p util.Period, isPatch bool) (bc *BuyChance) {
	bc = new(BuyChance)
	//	bc.Type = util.ModeType(data.DwModel) | util.MODE_SUIJI_202 | util.MODE_SUIJI_201
	//	bc.Type = bc.Type - util.MODE_SUIJI_202 - util.MODE_SUIJI_201
	bc.Type = GetModeType(data.NModelMask)
	if bc.Type == 0 {
		r_log.BCLogger.Info("BC(period = %v, isPatch = %v): filter suiji: stkid=%v", p, isPatch, data.Info.IdStk)
		return nil
	}
	//	if util.ModeType(data.DwModel)&MODE_ZHENDANG2 > 0 {
	//		bc.Type -= MODE_ZHENDANG2
	//		bc.Type = bc.Type | MODE_ZHENDANG
	//	}
	//	if util.ModeType(data.DwModel)&MODE_BOTHCHAODIE > 0 {
	//		bc.Type -= MODE_BOTHCHAODIE
	//		bc.Type = bc.Type | MODE_CHAODIE
	//	}
	bc.IsKC = false
	bc.IsCY = false
	if marketcode, ok := s.StkMapSH[data.Info.IdStk]; ok {
		if strings.HasPrefix(marketcode, "SHHQ68") {
			bc.IsKC = true
		}
	}
	if marketcode, ok := s.StkMapSZ[data.Info.IdStk]; ok {
		if strings.HasPrefix(marketcode, "SZHQ30") {
			bc.IsCY = true
		}
	}

	bc.Stkid = util.StkID(data.Info.IdStk)
	bc.Price[0] = data.NClose / 10
	bc.Price[1] = data.NPrice50 / 10
	bc.Price[2] = data.NPrice70 / 10
	bc.Price[3] = data.NPrice80 / 10
	bc.Price[4] = data.NPrice85 / 10
	bc.Price[5] = data.NPrice95 / 10
	bc.NMaxLoss = data.ItemFixed2.NMaxLoss
	bc.NProfitRate = data.ItemFixed2.NProfitRate
	bc.NSuccRate = data.ItemFixed2.NSuccRate
	bc.Market |= util.MarketCode(data.NIn_BR01B00001)
	bc.Market |= 1 << util.MarketCode(data.NIn_BR01B00002)
	bc.Market |= 2 << util.MarketCode(data.NIn_BR01B00007)
	bc.Market |= 3 << util.MarketCode(data.NIn_BR01B00014)
	bc.Market |= 4 << util.MarketCode(data.NIn_BR01B00024)
	bc.Market |= 5 << util.MarketCode(data.NIn_BR01B00035)
	bc.Market |= 6 << util.MarketCode(data.NIn_BR01B00036)
	bc.Market |= 7 << util.MarketCode(data.NIn_BR01B00037)
	bc.Market |= 8 << util.MarketCode(data.NIn_BR01B02149)
	bc.Market |= 9 << util.MarketCode(data.NIn_BR01B06100)
	bc.Market |= 10 << util.MarketCode(data.NIn_BR01B06305)
	bc.Market |= 11 << util.MarketCode(data.NIn_BR01B06501)
	bc.AvgTransaction = data.NAvgAmount5 * 100
	bc.Date = util.DateAndTime(data.Info.DwDate)
	bc.Level = util.LEVEL_UNKNOWN
	//bc.Level = util.LEVEL_A
	bc.CountinueLose = data.NCountinueLose > 0
	bc.Time = util.DateAndTime(data.Info.DwUion)
	if bc.Time > 150000 || p == util.PERIOD_DAY {
		bc.Time = 150000 //data.Info.DwUion
	}

	return
}

//滤网包结构转换
func convertMF(data SDds_Quantitative_ModelFilter) (mf ModeFilter) {
	mf.Stkid = util.StkID(data.Info.IdStk)
	mf.Date = util.DateAndTime(data.Info.DwDate)
	mf.Time = util.DateAndTime(data.Info.DwUion)
	mf.Level[0] = data.BtFlagA > 0
	mf.Level[1] = data.BtFlagB > 0
	mf.Level[2] = data.BtFlagC > 0
	mf.Level[3] = data.BtFlagD > 0
	return
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
type Kline struct {
	Open  int32
	High  int32
	Low   int32
	Close int32
}

func (s *DataSocket) Deal83(data SDds_I_Dyn_Stk_L1) { //日线
	//fmt.Println(data.Info.IdStk, data.N1.NNewest)
	//	newPrice.MapLock.Lock()
	//	if marketcode, ok := s.StkMap[data.Info.IdStk]; ok {
	//		newPrice.StkMap[marketcode] = float32(data.N1.NNewest) / 100
	//	}
	//	newPrice.MapLock.Unlock()
	<-s.ThreadChan
}

func (s *DataSocket) Deal83Patch(data SDds_I_Dyn_Stk_L1) { //日线
	//fmt.Println(data.Info.IdStk, data.N1.NNewest)
	//	newPrice.MapLock.Lock()
	//	if marketcode, ok := s.StkMap[data.Info.IdStk]; ok {
	//		newPrice.StkMap[marketcode] = float32(data.N1.NNewest) / 100
	//	}
	//	newPrice.MapLock.Unlock()
	<-s.ThreadChan
}
